home *** CD-ROM | disk | FTP | other *** search
- PROGRAM gouraud2;
- {
- Gouraud shading or what? Part 2!
- - by Bjarke Viksφe
- aug 1994
- }
-
- {{$DEFINE DEBUG}
-
- USES
- DEMOINIT;
-
- CONST
- NUMBER_FACES = 6;
- NUMBER_COORDS = 8;
- box = 110; {size of box}
-
- TYPE
- SlopeType = array[0..320*2] of integer;
-
- FaceType = RECORD
- l1,l2,l3,l4 : byte;
- end;
-
-
- VAR
- slope,zslope : SlopeType;
- face : array[1..NUMBER_FACES] of FaceType;
- cbuffer : array[0..NUMBER_COORDS*4-1] of integer;
-
- minx,maxx : integer;
-
- sinustabel : array[0..639] of integer;
- v1,v2,v3 : word;
- cos1,sin1,cos2,sin2,cos3,sin3 : integer;
-
-
- CONST
- display1 : word = $0000;
- display2 : word = $4000;
- {setup coords for a box}
- coords : array[0..NUMBER_COORDS*3-1] of integer =
- (box,box,-box, -box,box,-box, -box,-box,-box, box,-box,-box,
- box,box,box, -box,box,box, -box,-box,box, box,-box,box);
-
-
- (*------------------------------------------------*)
-
- procedure SetupSinus;
- var
- i : integer;
- v, vadd : real;
- begin
- v:=0.0;
- vadd:=(2.0*pi/512.0);
- for i:=0 to 639 do begin
- sinustabel[i]:=round(sin(v)*32767);
- v:=v+vadd;
- end;
- end;
-
- procedure SetupFaces;
- {setup faces. Make sure face keeps track of which coordinates it uses!}
- begin
- with face[1] do begin l1:=3; l2:=2; l3:=1; l4:=0; end;
- with face[2] do begin l1:=4; l2:=5; l3:=6; l4:=7; end;
- with face[3] do begin l1:=0; l2:=1; l3:=5; l4:=4; end;
- with face[4] do begin l1:=1; l2:=2; l3:=6; l4:=5; end;
- with face[5] do begin l1:=2; l2:=3; l3:=7; l4:=6; end;
- with face[6] do begin l1:=3; l2:=0; l3:=4; l4:=7; end;
- end;
-
- procedure InitDemo;
- var
- i : integer;
- begin
- Screen_Off;
- ClearWholeScreen;
- SetupSinus;
- SetupFaces;
-
- v1:=0; v2:=0; v3:=0;
-
- for i:=1 to 63 do SetRGB(i,0,64-i,0);
- for i:=64 to 255 do SetRGB(i,0,0,0);
-
- Screen_On;
- end;
-
-
- (*------------------------------------------------*)
-
- procedure SwapDisplay;
- var
- temp : word;
- begin
- temp:=display2;
- display2:=display1;
- display1:=temp;
- SetAddress(Ptr(SEGA000,display2));
- end;
-
- procedure ClearScreen; assembler;
- asm
- mov dx,$3C4
- mov ax,$0F02
- out dx,ax
-
- mov es,SEGA000
- mov di,display1
- add di,(30*WIDTH)+16
- mov dx,140
- xor ax,ax
- mov bx,48/2
- @loop:
- mov cx,bx
- rep stosw
- add di,WIDTH-48
- dec dl
- jnz @loop
- end;
-
-
- (*------------------------------------------------*)
-
- procedure ClearSlope; assembler;
- asm
- mov ax,ds
- mov es,ax
- lea di,slope
- DB LONG; mov ax,$8000; DW $8000;
- cld
- mov cx,TYPE(slopetype)/4
- rep; DB LONG; stosw
- end;
-
-
- procedure CalcSlope(l1,l2 : integer); assembler;
- var
- z1,z2,coladd : word;
- xlowadd : word;
- ysize : integer;
- asm
- lea si,cbuffer
- DB LONG; xor cx,cx
- mov bx,l1 {get first coords}
- shl bx,3
- mov ax,[si+bx+4] {get z value}
- mov z2,ax
- mov dx,[si+bx] {get x/y coords}
- mov cx,[si+bx+2]
-
- mov ax,l2 {get second coords}
- shl ax,3
- add si,ax
- mov ax,[si+4] {get z value}
- mov z1,ax
- mov ax,[si] {get x/y coords}
- mov bx,[si+2]
-
- cmp bx,cx {make sure we go downwards...}
- jle @noswap
- mov si,z1 {swap z}
- xchg z2,si
- mov z1,si
- xchg ax,dx {swap x}
- xchg bx,cx {sway y}
- @noswap:
-
- cmp bx,minx {record miny and maxy}
- jae @minx
- mov minx,bx
- @minx:
- cmp cx,maxx
- jbe @maxx
- mov maxx,cx
- @maxx:
-
- sub cx,bx {find y-size}
- jcxz @zero
- mov ysize,cx
- add bx,bx
- add bx,bx
- lea si,slope
- add si,bx
-
- push ax
- sub dx,ax
-
- mov ax,dx {calc x-slope run}
- DB LONG; shl ax,16
- {cdq} DB $66,$99
- DB LONG; idiv cx
- DB LONG; mov dx,ax
- DB LONG; shr dx,16
- mov xlowadd,ax
- {DX also loaded... but kept alive}
-
- push dx {also calc z-slope run}
- mov dh,BYTE PTR z1
- mov ah,BYTE PTR z2
- sub ah,dh
- xor al,al
- cwd
- idiv cx
- mov coladd,ax
- pop dx
- @one:
- pop cx
-
- xor bx,bx
- mov ah,BYTE PTR z1 {prepare also z-slope calc. z1:=z1*256}
- xor al,al
- mov di,$8000
- @loop:
- cmp [si],di {is first slot filled?}
- jne @other {yes, put it in 2nd}
- mov [si+TYPE(SlopeType)],ah {insert z-coord}
- mov [si],cx {insert x-coord}
- add bx,xlowadd {add to x-coord}
- adc cx,dx
- add ax,coladd {add to z-coord}
- add si,4 {next slot...}
- dec ysize
- jnz @loop
- jmp NEAR PTR @zero
- @other:
- mov [si+TYPE(SlopeType)+2],ah
- mov [si+2],cx
- add bx,xlowadd
- adc cx,dx
- add ax,coladd
- add si,4
- dec ysize
- jnz @loop
- @zero:
- end;
-
-
- (*------------------------------------------------*)
-
- procedure CalcAngle;
- begin
- sin1:=sinustabel[v1]; cos1:=sinustabel[v1+128];
- sin2:=sinustabel[v2]; cos2:=sinustabel[v2+128];
- sin3:=sinustabel[v3]; cos3:=sinustabel[v3+128];
- v1:=(v1+2) AND 511;
- v2:=(v2-1) AND 511;
- v3:=(v3+1) AND 511;
- end;
-
- procedure RotateAllCoords; assembler;
- {Rotate all coords in "coords" around all 3 axis and make
- perspective calcualtion. Store x,y,z results in "cbuffer"}
- var
- xkoord,ykoord,zkoord, n : integer;
- asm
- mov ax,ds
- mov es,ax
- lea si,coords
- lea di,cbuffer
- mov n,NUMBER_COORDS
- cld
- @loop:
- lodsw
- mov xkoord,ax
- lodsw
- mov ykoord,ax
- lodsw
- mov zkoord,ax
-
- mov ax,xkoord {rotate around Z-axis}
- push ax
- imul Cos1
- add ax,ax
- adc dx,dx
- mov bx,dx
- mov ax,ykoord
- imul Sin1
- add ax,ax
- adc dx,dx
- sub bx,dx
- mov xkoord,bx
- pop ax
- imul Sin1
- add ax,ax
- adc dx,dx
- mov bx,dx
- mov ax,ykoord
- imul Cos1
- add ax,ax
- adc dx,dx
- add bx,dx
- mov ykoord,bx
-
- mov ax,ykoord {rotate around Y-axis}
- push ax
- imul Cos2
- add ax,ax
- adc dx,dx
- mov bx,dx
- mov ax,zkoord
- imul Sin2
- add ax,ax
- adc dx,dx
- sub bx,dx
- mov ykoord,bx
- pop ax
- imul Sin2
- add ax,ax
- adc dx,dx
- mov bx,dx
- mov ax,zkoord
- imul Cos2
- add ax,ax
- adc dx,dx
- add bx,dx
- mov zkoord,bx
-
- mov ax,xkoord {rotate around X-axis}
- push ax
- imul Cos3
- add ax,ax
- adc dx,dx
- mov bx,dx
- mov ax,zkoord
- imul Sin3
- add ax,ax
- adc dx,dx
- sub bx,dx
- mov xkoord,bx
- pop ax
- imul Sin3
- add ax,ax
- adc dx,dx
- mov bx,dx
- mov ax,zkoord
- imul Cos3
- add ax,ax
- adc dx,dx
- add bx,dx
- mov zkoord,bx
-
- add bx,800
- and bx,bx
- jnz @zero
- mov bl,1
- @zero:
-
- mov ax,xkoord
- cwd
- mov dl,ah
- mov ah,al
- xor al,al
- idiv bx
- add ax,100
- stosw
-
- mov ax,ykoord
- cwd
- mov dl,ah
- mov ah,al
- xor al,al
- idiv bx
- add ax,160
- stosw
-
- mov ax,bx
- sub ax,390
- shr ax,2
- stosw
- add di,2
-
- dec n
- jnz @loop
- end;
-
-
-
- function FaceShown(l1,l2,l3 : byte) : boolean;
- var
- a,b : longint;
- begin
- a := longmul(cbuffer[l1]-cbuffer[l2],cbuffer[l3+1]-cbuffer[l2+1]);
- b := longmul(cbuffer[l1+1]-cbuffer[l2+1],cbuffer[l3]-cbuffer[l2]);
- FaceShown := (a-b) > 0;
- end;
-
-
- procedure FillShape(x,xsize : integer); assembler;
- var
- z1,z2 : byte;
- bitxpos : byte;
- asm
- cmp xsize,200
- jae @done
- mov ax,x
- sar ax,2
- add ax,display1
- mov di,ax
-
- lea si,slope
- mov ax,x
- mov cx,ax
- shl ax,2
- add si,ax
-
- and cl,3
- mov al,$11
- shl al,cl
- mov [bitxpos],al
-
- mov es,SEGA000
- mov dx,$3C4
- mov al,$02
- out dx,al
- cld
- @xloop:
- mov bh,[si+TYPE(slopetype)] {fetch z value}
- lodsw {fetch first xpos}
- mov dx,ax
- mov bl,[si+TYPE(slopetype)] {fetch second z value}
- lodsw {fetch second xpos}
- cmp ax,dx
- jle @exchange
- xchg ax,dx
- xchg bl,bh
- @exchange:
- mov z1,bl
- mov z2,bh
-
- cmp dx,0
- jl @filledout_fast
- cmp ax,200
- jge @filledout_fast
- cmp ax,0
- jge @cut1
- xor ax,ax
- @cut1:
- cmp dx,199
- jle @cut2
- mov dx,199
- @cut2:
- push si
- push di
-
- mov bx,ax {find VGA address offset}
- add bx,bx
- add di,[OFFSET ytabel+bx]
-
- mov cx,dx {find height of line}
- sub cx,ax
- jcxz @filledout
- push cx
-
- mov ah,z2 {prepare z-slope run}
- sub ah,z1
- xor al,al
- cwd
- idiv cx
- mov bx,ax
-
- mov dx,$3C5 {set VGA bitplane register}
- mov al,[bitxpos]
- out dx,al
-
- mov ah,z1 {prepare z-slope run}
- xor al,al
- mov dx,WIDTH
- pop cx
- @loop:
- add ax,bx {add to z-coord run}
- mov ch,ah {get z-coord}
- shr ch,1
- mov [es:di],ch {put z-coord on VGA display as colour}
- add di,dx {find next VGA line}
- dec cl
- jnz @loop
-
- @filledout:
- pop di
- pop si
- @filledout_fast:
- rol [bitxpos],1
- adc di,0 {find next x-position}
- @no_address_add:
- dec xsize
- jnz @xloop
- @done:
- end;
-
-
- procedure RunOnce;
- var
- i : integer;
- begin
- SwapDisplay;
- VBLANK;
- {$IFDEF DEBUG}
- SetRGB(0,30,0,0);
- {$ENDIF}
-
- ClearScreen;
-
- CalcAngle;
- RotateAllCoords;
-
- for i:=1 to NUMBER_FACES do begin
- with face[i] do if FaceShown(l1 SHL 2,l2 SHL 2,l3 SHL 2) then begin
- ClearSlope;
- minx := 200; maxx := 0;
- CalcSlope(l1,l2);
- CalcSlope(l2,l3);
- CalcSlope(l3,l4);
- CalcSlope(l4,l1);
- FillShape(minx, maxx-minx);
- end;
- end;
-
- {$IFDEF DEBUG}
- SetRGB(0,0,0,0);
- while KeyHit[26] do ; {Hit 'P' to pause}
- {$ENDIF}
- end;
-
-
- begin
- OpenScreen;
- InitDemo;
- SetAllInterrupts;
- repeat RunOnce until Key='e';
- RestoreAllInterrupts;
- CloseScreen;
- end.
-